/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.classdiagram.tabbedproperties.section;

import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.uml2.uml.Abstraction;
import org.eclipse.uml2.uml.OpaqueExpression;
import org.eclipse.uml2.uml.UMLFactory;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.GraphEdgeEditPart;
import com.cea.papyrus.core.editpart.GraphNodeEditPart;
import com.cea.papyrus.core.editpart.IUMLElementEditPart;
import com.cea.papyrus.core.tabbedproperties.PropertyViewSection;
import com.cea.papyrus.diagram.classdiagram.tabbedproperties.composite.OpaqueExpressionBodiesComposite;
import com.cea.papyrus.diagraminterchange2.di2.DiagramElement;

/**
 * 
 */
public class AbstractionMappingSection extends PropertyViewSection {


	/**
	 * 
	 */
	private Button addButton, removeButton; 
	
	/**
	 * 
	 */
	private CLabel SFLabel;
	
	/**
	 * 
	 */
	private Composite parent, composite;
	
	/**
	 * 
	 */
	private OpaqueExpression mapping;
	
	/**
	 * 
	 */
	private OpaqueExpressionBodiesComposite opaqueExpressionComposite;
	
	/**
	 * 
	 */
	private Text editionArea;
	
	/**
	 * Listener for the delete button.
	 */
	protected MouseListener removeButtonListener;
	
	/**
	 * Listener for the up button.
	 */
	protected MouseListener addButtonListener;
	
	/**
	 * 
	 */
	protected SelectionListener tableListener;
	
	/**
	 * 
	 */
	protected FocusListener editionAreaListener;
	
	/**
	 * 
	 */
	private IUMLElementEditPart abstractionEditPart;
	
	/**
	 * 
	 */
	private final org.eclipse.swt.graphics.Image remove_img 
	= PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16+"Delete_16x16.gif");
	
	/**
	 * 
	 */
	private final org.eclipse.swt.graphics.Image add_img
	= PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16+"Add_16x16.gif");
	
	/**
	 * 
	 */
	private final org.eclipse.swt.graphics.Image edit_img
	= PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16+"SegmentEdit_16x16.gif");


	/**
	 * 
	 */
	private ModelManager modelManager;

	

	/**
	 * 
	 * 
	 * @param tabbedPropertySheetPage 
	 * @param parent 
	 */
	@Override
	public void createControls(Composite parent,
			TabbedPropertySheetPage tabbedPropertySheetPage) {
		super.createControls(parent, tabbedPropertySheetPage);
		composite = getWidgetFactory().createFlatFormComposite(parent);
		this.parent=parent;
		FormData data;

		
		getWidgetFactory().createCLabel(composite, "Mapping:"); //$NON-NLS-1$
		
				
		// defining structural feature label
		SFLabel = getWidgetFactory().createCLabel(composite, "", SWT.BORDER);
		data = new FormData();
		data.left = new FormAttachment(0, STANDARD_LABEL_WIDTH);
		data.right = new FormAttachment(30);
		data.top = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
		SFLabel.setLayoutData(data);
		
		// browseButton layout
		addButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
		addButton.setImage(add_img);
		data = new FormData();
		data.left = new FormAttachment(SFLabel, ITabbedPropertyConstants.HSPACE);
		data.top  = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
		addButton.setLayoutData(data);

		// removeButton layout
		removeButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
		removeButton.setImage(remove_img);
		data = new FormData();
		data.left = new FormAttachment(addButton, ITabbedPropertyConstants.HSPACE);
		data.top  = new FormAttachment(addButton, 0, SWT.CENTER);
		removeButton.setLayoutData(data);
		
		
		// listeners setting
		addButtonListener = new AddButtonlistener();
		addButton.addMouseListener(addButtonListener);
		removeButtonListener = new RemoveButtonlistener();
		removeButton.addMouseListener(removeButtonListener);

		
		opaqueExpressionComposite = new OpaqueExpressionBodiesComposite();
		opaqueExpressionComposite.createContent(composite, getWidgetFactory());
		data = new FormData();
		data.left = new FormAttachment(0);
		data.right = new FormAttachment(removeButton);
		data.top = new FormAttachment(addButton, ITabbedPropertyConstants.HSPACE);
		opaqueExpressionComposite.setLayoutData(data);
		
		
		// edition area
		editionArea = getWidgetFactory().createText(composite, "", SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
		data = new FormData();
		data.left = new FormAttachment(removeButton, ITabbedPropertyConstants.VSPACE);
		data.right = new FormAttachment(100);
		data.top = new FormAttachment(addButton, ITabbedPropertyConstants.HSPACE);
		data.bottom = new FormAttachment(97);
		editionArea.setLayoutData(data);
		
		
		// Listener for edition
		final Table table = opaqueExpressionComposite.getTable();
		table.addSelectionListener(tableListener = new SelectionListener() {
			
			public void widgetSelected(SelectionEvent e) {
				int selectionIndex = table.getSelectionIndex();
				if(selectionIndex != -1){ // selection not null
					OpaqueExpression opaqueExpressionElement = (OpaqueExpression)opaqueExpressionComposite.getElement().getUml2Element();
					editionArea.setText((String)(opaqueExpressionElement).getBodies().get(selectionIndex));
				}
			}
			
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});
		
		
		editionArea.addFocusListener(editionAreaListener = new FocusListener() {
    		public void focusGained(FocusEvent e){
    		}
    		public void focusLost(FocusEvent e){
    			if((table.getSelection() != null) && (table.getSelection().length > 0)) {
    				int selectionIndex = table.getSelectionIndex();
    				OpaqueExpression opaqueExpressionElement = (OpaqueExpression)opaqueExpressionComposite.getElement().getUml2Element();
    				opaqueExpressionElement.getBodies().set(selectionIndex, editionArea.getText().trim());
    			}
    			refresh();
    		}
        });

		editionArea.setToolTipText("Body edition area");

	}



	/*
	 * @see org.eclipse.ui.views.properties.tabbed.view.ITabbedPropertySection#refresh()
	 */
	/**
	 * 
	 */
	@Override
	public void refresh() {
		if(!addButton.isDisposed()){
			if(getElement() instanceof Abstraction){
				if(((Abstraction)getElement()).getMapping()==null) {
					SFLabel.setText("UndefinedMapping");
					addButton.setEnabled(true);
					removeButton.setEnabled(false);
				}

				else {
					SFLabel.setText(((Abstraction)getElement()).getMapping().getName());
					removeButton.setEnabled(true);
					addButton.setEnabled(false);
					
					mapping = ((Abstraction)getElement()).getMapping();
					com.cea.papyrus.umlutils.OpaqueExpression opaqueExpression = new com.cea.papyrus.umlutils.OpaqueExpression(mapping);
					opaqueExpressionComposite.setElement(opaqueExpression);
				}
				opaqueExpressionComposite.refresh();
				editionAreaRrefresh();
			}
		}		
	}
	
	/**
	 * editionArea refresh operation.
	 */
	private void editionAreaRrefresh() {
		if(opaqueExpressionComposite.getTable().getSelectionCount()==0)
			editionArea.setText("");
	}
	
	/**
	 * Listener for the Remove Button
	 * Specific behavior is implemented in removeButtonPressed.
	 * 
	 * @author Chokri Mraidha
	 */
	protected class RemoveButtonlistener implements MouseListener {
		
		/**
		 * 
		 * 
		 * @param e 
		 */
		public void mouseDoubleClick(MouseEvent e) {
			// do nothing
		}
		
		/**
		 * 
		 * 
		 * @param e 
		 */
		public void mouseDown(MouseEvent e) {
			// do nothing
		}
		
		/**
		 * 
		 * 
		 * @param e 
		 */
		public void mouseUp(MouseEvent e) {
			removeButtonPressed();
			refresh();
		}
	}
	
	
	/**
	 * Listener for the Add Button
	 * Specific behavior is implemented in addButtonPressed.
	 * 
	 * @author Chokri Mraidha
	 */
	protected class AddButtonlistener implements MouseListener {
		
		/**
		 * 
		 * 
		 * @param e 
		 */
		public void mouseDoubleClick(MouseEvent e) {
			// do nothing
		}
		
		/**
		 * 
		 * 
		 * @param e 
		 */
		public void mouseDown(MouseEvent e) {
			// do nothing
		}
		
		/**
		 * 
		 * 
		 * @param e 
		 */
		public void mouseUp(MouseEvent e) {
			addButtonPressed();
			refresh();
		}
	}

	
	/**
	 * behavior executed when remove button is pressed.
	 */
	protected void removeButtonPressed(){
		if(getElement() instanceof Abstraction){
			opaqueExpressionComposite.removeAllOpaqueExpressionDisplay(mapping);
			((Abstraction)getElement()).setMapping(null);
			opaqueExpressionComposite.setElement(null);
			opaqueExpressionComposite.refresh();
		}
	}
	
	/**
	 * behavior executed when browse button is pressed.
	 */
	protected void addButtonPressed(){
		if(getElement() instanceof Abstraction){
			mapping = UMLFactory.eINSTANCE.createOpaqueExpression();
			mapping.setName("DefinedMapping");
			((Abstraction)getElement()).setMapping(mapping);
			com.cea.papyrus.umlutils.OpaqueExpression opaqueExpression = new com.cea.papyrus.umlutils.OpaqueExpression(mapping);
			opaqueExpressionComposite.setElement(opaqueExpression);
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.properties.tabbed.PropertyViewSection#setInput(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
	 */
	/**
	 * 
	 * 
	 * @param part 
	 * @param selection 
	 */
	public void setInput(IWorkbenchPart part, ISelection selection) {
		super.setInput(part, selection);
		Object input = ((IStructuredSelection) selection).getFirstElement();
		if(input instanceof IUMLElementEditPart) {
			this.modelManager = ((IUMLElementEditPart) input).getModelManager();
			abstractionEditPart = (IUMLElementEditPart)input;
			opaqueExpressionComposite.setModelManager(this.modelManager);

			if((input instanceof GraphNodeEditPart) || (input instanceof GraphEdgeEditPart)){
				diagramElement = (DiagramElement)((AbstractGraphicalEditPart)input).getModel();
				opaqueExpressionComposite.setDiagramElement(diagramElement);
			}
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.properties.tabbed.PropertyViewSection#dispose()
	 */
	/**
	 * 
	 */
	public void dispose(){
		super.dispose();
		if(addButton!=null && !addButton.isDisposed())
			addButton.removeMouseListener(addButtonListener);
		if(removeButton!=null && !removeButton.isDisposed())
			removeButton.removeMouseListener(removeButtonListener);
		if(opaqueExpressionComposite!=null && opaqueExpressionComposite.getTable()!=null && !opaqueExpressionComposite.getTable().isDisposed())
			opaqueExpressionComposite.getTable().removeSelectionListener(tableListener);
		if(editionArea!=null && !editionArea.isDisposed())
			editionArea.removeFocusListener(editionAreaListener);
		if(opaqueExpressionComposite!=null)
			opaqueExpressionComposite.dispose();
	}

}


